<template>
  <h1>X6</h1>
  <div class="wrapper">
    <div class="app">
      <!-- 左侧拖拽区域 -->
      <div class="dnd-wrap">
        <!-- data-type 拖拽节点类型 -->
        <div data-type="rect" class="dnd-rect" @mousedown="startDrag">
          Rect
        </div>
        <div data-type="circle" class="dnd-circle" @mousedown="startDrag">
          Circle
        </div>
      </div>

      <!-- 右侧展示流程 -->
      <div class="app-content" ref="refContainer" />
    </div>
  </div>
</template>

<script>
import { Graph, Addon } from '@antv/x6';
import { onMounted, ref } from "vue";

const { Dnd } = Addon;
export default {
  setup () {
    let dnd; //拖拽插件
    const refContainer = ref(); //画布dom
    let graph; //画布

    const ports = {
      groups: {
        // 输入链接桩群组定义
        in: {
          position: 'top',
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: '#31d0c6',
              strokeWidth: 2,
              fill: '#fff',
            },
          },
        },
        // 输出链接桩群组定义
        out: {
          position: 'bottom',
          attrs: {
            circle: {
              r: 6,
              magnet: true,
              stroke: '#31d0c6',
              strokeWidth: 2,
              fill: '#fff',
            },
          },
        },
      },
      items: [
        // {
        //   id: 'port1',
        //   group: 'in',
        // },
      ],
    }

    onMounted(() => {
      // 初始化 画布配置
      graph = new Graph({
        width: 600,
        height: 400,
        container: refContainer.value,
        grid: true,
        history: true,
        selecting: {
          className: 'my-selecting', //自定义样式
          enabled: true,
          rubberband: true,
          showNodeSelectionBox: true, //展示节点选择框
          multiple: false, //是否允许多选
        }, //点击节点
        snapline: {
          enabled: true,
          sharp: true,
        },
        scroller: {
          enabled: true,
          pageVisible: false,
          pageBreak: false,
          pannable: true,
        },
        mousewheel: {
          enabled: true,
          modifiers: ['ctrl', 'meta'],
        },
        connecting: {
          snap: true,
          allowBlank: false, //允许连接空白
          allowMulti: false, //允许相同连接桩重复连接
          allowEdge: false, //允许连接另一条边
        }
      });

      graph.fromJSON({}); //渲染画布数据
      graph.centerContent(); //画布视口居中

      // 点击节点选中
      graph.on('node:selected', ({
        cell,
        node,
        options,
      }) => {
        // code here
        console.log(cell, node, options);
      })

      dnd = new Dnd({
        target: graph,
        scaled: false,
        animation: true,
        getDropNode, // 拖拽结束放下节点
      })
    })

    // 点击左侧,鼠标按下开始拖拽
    const startDrag = (e) => {
      const target = e.currentTarget;
      const type = target.getAttribute("data-type");
      // 根据目标类型生成对应源节点
      const node =
        type === "rect"
          ? graph.createNode({
            width: 100,
            height: 40,
            id: 'hello',
            attrs: {
              label: {
                text: "Rect",
                fill: "#6a6c8a"
              },
              body: {
                stroke: "#31d0c6",
                strokeWidth: 2
              }
            },
            ports
          })
          : graph.createNode({
            width: 60,
            height: 60,
            shape: "html",
            html: () => {
              const wrap = document.createElement("div");
              wrap.style.width = "100%";
              wrap.style.height = "100%";
              wrap.style.display = "flex";
              wrap.style.alignItems = "center";
              wrap.style.justifyContent = "center";
              wrap.style.border = "2px solid rgb(49, 208, 198)";
              wrap.style.background = "#fff";
              wrap.style.borderRadius = "100%";
              wrap.innerText = "Circle";
              return wrap;
            },
            ports
          });

      dnd.start(node, e);
    };

    // 拖拽结束时配置连接桩
    const getDropNode = (draggingNode, options) => {
      // 添加连接桩
      draggingNode.addPorts([{ group: 'in' }, { group: 'in' }, { group: 'out' }, { group: 'out' },])
      return draggingNode.clone({ keepId: true })
    }

    const data = {
      // 节点
      nodes: [
        {
          x: 130,
          y: 30,
          width: 100,
          height: 40,
          attrs: {
            label: {
              text: 'Hello',
              fill: '#6a6c8a',
            },
            body: {
              stroke: '#31d0c6',
              strokeWidth: 2,
            },
          },
          id: "node1"
        },
        {
          id: 'node2', // String，节点的唯一标识
          x: 180,
          y: 160,
          width: 100,
          height: 40,
          attrs: {
            label: {
              text: 'World',
              fill: '#6a6c8a',
            },
            body: {
              stroke: '#31d0c6',
              strokeWidth: 2,
            },
          },
        },
      ],
      // 边
      edges: [
        {
          source: 'node1', // String，必须，起始节点 id
          target: 'node2', // String，必须，目标节点 id
        },
      ],
    };

    return { startDrag, refContainer };
  },
};
</script>
<style lang="less">
.wrapper {
  display: flex;
  justify-content: center;
}
.app {
  font-family: sans-serif;
  padding: 0;
  display: flex;
  padding: 16px 8px;
}

// 选中框样式
.my-selecting {
  .x6-widget-selection-box {
    border-color: red;
  }
}

.app-content {
  flex: 1;
  height: 240px;
  margin-left: 8px;
  margin-right: 8px;
  box-shadow: 0 0 10px 1px #e9e9e9;
}

.dnd-wrap {
  width: 200px;
  padding: 16px;
  border: 1px solid #f0f0f0;
  display: flex;
  flex-direction: column;
  align-items: center;
  user-select: none;
}

.dnd-rect {
  width: 100px;
  height: 40px;
  border: 2px solid #31d0c6;
  text-align: center;
  line-height: 40px;
  margin: 16px;
  cursor: move;
}

.dnd-circle {
  width: 60px;
  height: 60px;
  border-radius: 100%;
  border: 2px solid #31d0c6;
  text-align: center;
  line-height: 60px;
  margin: 16px;
  cursor: move;
}

.x6-graph-scroller {
  border: 1px solid #f0f0f0;
  margin-left: -1px;
}

.validating {
  position: relative;
}

.validating:after {
  position: absolute;
  top: 4px;
  left: 4px;
  content: " ";
  display: block;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 6px solid #873bf4;
  border-color: #873bf4 transparent #873bf4 transparent;
  animation: lds-dual-ring 1.2s linear infinite;
}

@keyframes lds-dual-ring {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>
